package im.yisme.model.record;

import im.yisme.model.LyricsAction;
import im.yisme.vo.RawActionVO;

import java.util.ArrayList;
import java.util.Iterator;

import android.view.MotionEvent;

public class StatusMachine {


	

	private Status [][] statusCode={{Status.Down},
			                        {Status.In,Status.Out},
									{Status.Move,Status.Up},
									{Status.Out,Status.In},
									{Status.Move,Status.Up,Status.Up,Status.Move},
									{Status.In,Status.Out},
									{Status.NewIn,Status.OriginalIn,Status.Move,Status.Up},
									{Status.Move,Status.Up},
									{Status.In,Status.Out},
									{Status.Move,Status.Up,Status.Move,Status.Up}};
	private Decision [][] decisionCode={{Decision.CheckInOrOut},
			 							{Decision.NewAndRecordMoment,Decision.Cancel},
			 							{Decision.CheckInOrOut,Decision.PrevTap},
			 							{Decision.PrevDragHead,Decision.WaitForNewInput},
			 							{Decision.CheckInOrOut,Decision.Cancel,Decision.PrevTap,Decision.JumpUp2Steps},
			 							{Decision.CheckOriginalInOrNewIn,Decision.WaitForNewInput},
			 							{Decision.NewAndRecordMomentAndDragConnection,Decision.Cancel,Decision.JumpUp2Steps,Decision.Cancel},
			 							{Decision.CheckInOrOut,Decision.PrevDragTail},
			 							{Decision.WaitForNewInput,Decision.WaitForNewInput},
			 							{Decision.JumpUp2Steps,Decision.PrevDragTail,Decision.JumpUp5Steps,Decision.Cancel}};
			
	private StatusTree tree;
	private ArrayList<LyricsAction> list;
	private StatusTreeNode currentNode;
	private boolean done;//状态机一次流水线是否结束
	
	private int lastPillar;//记录上一次手势点所在的Pillar
	
	public StatusMachine(){
		tree=new StatusTree();
		tree.createTree(statusCode, decisionCode);
		list=new ArrayList<LyricsAction>();
	}
	public void reset(){
		tree.reset();
		currentNode=tree.getCurrentNode();
		done=false;
		list.clear();
	}
	/**
	 * 
	 * @param action
	 * @return true:状态机结束，false:状态机未结束
	 */
	public boolean move(RawActionVO action){
				
		if(action.getAction() == MotionEvent.ACTION_MOVE){
			if(currentNode.getLeftChild().getStatus() == Status.Move)
				tree.moveLeft();
			else
				tree.moveRight();
		}
		else if(action.getAction() == MotionEvent.ACTION_UP){
			if(currentNode.getLeftChild().getStatus() == Status.Up)
				tree.moveLeft();
			else
				tree.moveRight();
		}
		
		currentNode=tree.getCurrentNode();
		Decision decision=currentNode.getDecision();
		
		makeDecision(decision,action);
		
		if(list.size() > 6) {
			done = true;
			list.clear();
		}
		
		return done;
	}
	
	private void makeDecision(Decision decision,RawActionVO action){
		
		switch (decision) {
		case CheckInOrOut:
			 
			 if(action.getWhichPillar() == -1){
				 if(currentNode.getLeftChild().getStatus() == Status.Out) 
					 tree.moveLeft();
				 else
					 tree.moveRight();
			 }
			 else{
				 if(currentNode.getLeftChild().getStatus() == Status.In) 
					 tree.moveLeft();
				 else
					 tree.moveRight();			 
			 }
			 
			 currentNode=tree.getCurrentNode();
			 makeDecision(currentNode.getDecision(), action);
			 break;
			 
		case NewAndRecordMoment:
			 
			 LyricsAction newAction=new LyricsAction(LyricsAction.TAP, (int)action.getMoment(), (byte)action.getWhichPillar(), LyricsAction.BEGIN_POINT);
			 list.add(newAction);
			 break;
			 
		case PrevTap:
			
			 LyricsAction prevAction1=list.get(list.size()-1);
			 prevAction1.setType(LyricsAction.TAP);
			 done=true;
			 break;
			 
			
		case PrevDragHead:
			
			 LyricsAction prevAction2=list.get(list.size()-1);
			 prevAction2.setType(LyricsAction.DRAG);
			 prevAction2.setConnectionType( LyricsAction.BEGIN_POINT );
		     lastPillar=prevAction2.getPoint();
			 break;
			
		case JumpUp2Steps:
			 
			 int count=2;
			 for(int i=0;i<count;i++) tree.moveUp();
			 currentNode=tree.getCurrentNode();
			 makeDecision(currentNode.getDecision() , action);
			 break;
			 
		case WaitForNewInput:
			 
			 break;
			 
		case Cancel:
			 
			 list.clear();
			 done=true;
			 break;
			 
		case CheckOriginalInOrNewIn:
			 
			 if(action.getWhichPillar() == lastPillar){
				 if(currentNode.getLeftChild().getStatus() == Status.OriginalIn)
					 tree.moveLeft();
				 else
					 tree.moveRight();
			 }
			 else{
				 if(currentNode.getLeftChild().getStatus() == Status.NewIn)
					 tree.moveLeft();
				 else
					 tree.moveRight();			 
			 }
			 
			 currentNode=tree.getCurrentNode();
			 makeDecision(currentNode.getDecision(), action);
			 break;
			 
		case NewAndRecordMomentAndDragConnection:
			 
			 LyricsAction newAction2=new LyricsAction(LyricsAction.DRAG, (int) action.getMoment(), (byte)action.getWhichPillar(), LyricsAction.LINK_POINT);
			 list.add(newAction2);
			 lastPillar=newAction2.getPoint();
			 break;
			 
		case PrevDragTail:
			 
			 LyricsAction prevAction3=list.get(list.size()-1);
			 prevAction3.setConnectionType(LyricsAction.END_POINT);
			 done=true;
			 break;
			 
		case JumpUp5Steps:
			 
			 int count2=5;
			 for(int j=0;j<count2;j++) tree.moveUp();
			 currentNode=tree.getCurrentNode();
			 makeDecision(currentNode.getDecision(), action);
			 break;

		default:
			break;
		}
	}
	public Iterator<LyricsAction> getProduct(){
		return list.iterator();
	}
	public Decision getCurrentDecision(){
		return currentNode.getDecision();
	}
}
